public class Test {
    public static void main(String[] args) throws Exception {
        Editor editor = new Editor();
        History history = new History();

        editor.write("Hello");
        history.push(editor.save()); // 存点

        editor.write(" Hello World");
        history.push(editor.save()); // 再存

        editor.write("!!!");
        System.out.println("当前: " + editor.getContent()); // Hello Hello World!!!

        editor.restore(history.pop()); // 撤销一次
        System.out.println("撤销后: " + editor.getContent()); // Hello Hello World

        editor.restore(history.pop()); // 再撤销
        System.out.println("再撤销: " + editor.getContent()); // Hello
    }
}
// 在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。

// 备忘录模式（Memento），主要用于捕获一个对象的内部状态，以便在将来的某个时候恢复此状态。

// 其实我们使用的几乎所有软件都用到了备忘录模式。最简单的备忘录模式就是保存到文件，打开文件。对于文本编辑器来说，保存就是把TextEditor类的字符串存储到文件，打开就是恢复TextEditor类的状态。
// 对于图像编辑器来说，原理是一样的，只是保存和恢复的数据格式比较复杂而已。Java的序列化也可以看作是备忘录模式。
/* ---------- 备忘录（不可变，仅对发起人可见） ---------- */
final class Memento {
    private final String state;

    Memento(String state) {
        this.state = state;
    }

    private String getState() {
        return state;
    }

    /* 只让 Editor 访问状态 */
    private static class PrivKey {
        private PrivKey() {
        }
    }

    static final PrivKey KEY = new PrivKey();

    String readState(PrivKey key) {
        return state;
    }
}

/* ---------- 发起人（会生成 & 读取备忘录） ---------- */
class Editor {
    private String content = "";

    void write(String text) {
        content += text;
    }

    String getContent() {
        return content;
    }

    Memento save() {
        return new Memento(content);
    }

    void restore(Memento m) {
        content = m.readState(Memento.KEY); // 用私有钥匙
    }
}

/* ---------- 管理者（只存备忘录，不碰内容） ---------- */
class History {
    private final java.util.Deque<Memento> stack = new java.util.ArrayDeque<>();

    void push(Memento m) {
        stack.push(m);
    }

    Memento pop() {
        return stack.isEmpty() ? null : stack.pop();
    }
}